// Package ast: 抽象语法树
package ast

import (
	"bytes"
	"fmt"
	"strings"
	"z-lang/token"
)

// Node 节点. 抽象语法树中的每个节点都必须实现Node接口
type Node interface {
	// TokenLiteral 返回当前节点的词法单元字面量
	TokenLiteral() string
	// String 打印节点信息
	String() string
}

// Statement 代码语句, 可以简单理解一行代码就是一个Statement
type Statement interface {
	Node
	statementNode()
}

// Expression 表达式
type Expression interface {
	Node
	expressionNode()
}

// Program 程序AST节点
type Program struct {
	Statements []Statement // 这个程序包含的代码语句，可以简单理解一行代码就是一个Statement
}

// TokenLiteral Program 实现Node接口
func (program *Program) TokenLiteral() string {
	if len(program.Statements) > 0 {
		return program.Statements[0].TokenLiteral()
	}
	return ""
}

// String Program 实现Node接口
func (program *Program) String() string {
	var out bytes.Buffer

	for _, s := range program.Statements {
		out.WriteString(s.String())
	}

	return out.String()
}

// LetStatement let语句结构定义
type LetStatement struct {
	Token token.Token // let 词法单元 token.LET
	Name  *Identifier // 标识符(变量名或函数名、参数名)指针
	Value Expression  // 表达式字面量
}

// TokenLiteral LetStatement实现Node接口TokenLiteral方法
func (ls *LetStatement) TokenLiteral() string {
	return ls.Token.Literal
}

// statementNode LetStatement实现Statement接口statementNode方法
func (ls *LetStatement) statementNode() {

}

// String LetStatement实现Node接口String方法
func (ls *LetStatement) String() string {
	var out bytes.Buffer

	out.WriteString(ls.TokenLiteral() + " ")
	out.WriteString(ls.Name.String())
	out.WriteString(" = ")

	if ls.Value != nil {
		out.WriteString(ls.Value.String())
	}

	out.WriteString(";")

	return out.String()
}

// Identifier 标识符(变量名或函数名、参数名)
type Identifier struct {
	Token token.Token // ident 词法单元 token.IDENT
	Value string      // 字面量 question: 按理来说, Token中已经有标识符的字面量了，为什么还要在这里又记录一次？
}

// TokenLiteral Identifier实现Node接口TokenLiteral方法
func (id *Identifier) TokenLiteral() string {
	return id.Token.Literal
}

// expressionNode Identifier实现Expression接口expressionNode方法
func (id *Identifier) expressionNode() {

}

// String Identifier实现Node接口String方法
func (id *Identifier) String() string {
	return id.Value
}

// ReturnStatement return语句结构定义
type ReturnStatement struct {
	Token       token.Token // return 词法单元 token.RETURN
	ReturnValue Expression  // 返回值 可能是实际数据，也可能是个表达式
}

// TokenLiteral ReturnStatement实现Node接口TokenLiteral方法
func (rs *ReturnStatement) TokenLiteral() string {
	return rs.Token.Literal
}

// statementNode ReturnStatement实现Statement接口statementNode方法
func (rs *ReturnStatement) statementNode() {

}

// String ReturnStatement实现Node接口String方法
func (rs *ReturnStatement) String() string {
	var out bytes.Buffer

	out.WriteString(rs.TokenLiteral() + " ")

	if rs.ReturnValue != nil {
		out.WriteString(rs.ReturnValue.String())
	}

	out.WriteString(";")

	return out.String()
}

// ExpressionStatement 表达式语句结构定义
type ExpressionStatement struct {
	Token      token.Token // expression 词法单元 该表达式中的第一个词法单元
	Expression Expression  // Expression 存储表达式的字面值
}

// TokenLiteral ExpressionStatement实现Node接口TokenLiteral方法
func (es *ExpressionStatement) TokenLiteral() string {
	return es.Token.Literal
}

// statementNode ExpressionStatement实现Statement接口statementNode方法
func (es *ExpressionStatement) statementNode() {

}

// String ExpressionStatement实现Node接口String方法
func (es *ExpressionStatement) String() string {
	if es.Expression != nil {
		return es.Expression.String()
	}
	return ""
}

// BlockStatement 代码块语句结构定义
type BlockStatement struct {
	Token      token.Token // 词法单元
	Statements []Statement // 代码块中的具体代码语句
}

// statementNode BlockStatement实现Statement接口statementNode方法
func (bs *BlockStatement) statementNode() {

}

// TokenLiteral BlockStatement实现Node接口TokenLiteral方法
func (bs *BlockStatement) TokenLiteral() string {
	return bs.Token.Literal
}

// String BlockStatement实现Node接口String方法
func (bs *BlockStatement) String() string {
	var out bytes.Buffer

	for _, st := range bs.Statements {
		out.WriteString(st.String())
	}

	return out.String()
}

// IntegerLiteral 整数字面量表达式结构定义
type IntegerLiteral struct {
	Token token.Token // 词法单元
	Value int64       // 整数字面量
}

// expressionNode IntegerLiteral实现Expression接口expressionNode方法
func (il *IntegerLiteral) expressionNode() {}

// TokenLiteral IntegerLiteral实现Node接口TokenLiteral方法
func (il *IntegerLiteral) TokenLiteral() string {
	return il.Token.Literal
}

// String IntegerLiteral实现Node接口String方法
func (il *IntegerLiteral) String() string {
	return il.Token.Literal
}

// PrefixExpression 前缀表达式解析结构定义 ( -5 !isTrue() )
type PrefixExpression struct {
	Token    token.Token // 词法单元
	Operator string      // 操作符
	Right    Expression  // 操作符右边的表达式
}

// expressionNode PrefixExpression实现Expression接口expressionNode方法
func (pe *PrefixExpression) expressionNode() {}

// TokenLiteral PrefixExpression实现Node接口TokenLiteral方法
func (pe *PrefixExpression) TokenLiteral() string {
	return pe.Token.Literal
}

// String PrefixExpression实现Node接口String方法
func (pe *PrefixExpression) String() string {
	var out bytes.Buffer

	out.WriteString("(")
	out.WriteString(pe.Operator)
	out.WriteString(pe.Right.String())
	out.WriteString(")")

	return out.String()
}

// InfixExpression 中缀表达式解析结构定义 ( 5 - 5 1 + 2 ... )
type InfixExpression struct {
	Token    token.Token // 词法单元
	Left     Expression  // 左侧表达式
	Operator string      // 操作符
	Right    Expression  // 右侧表达式
}

// expressionNode InfixExpression实现Expression接口expressionNode方法
func (ie *InfixExpression) expressionNode() {}

// TokenLiteral InfixExpression实现Node接口TokenLiteral方法
func (ie *InfixExpression) TokenLiteral() string {
	return ie.Token.Literal
}

// String InfixExpression实现Node接口String方法
func (ie *InfixExpression) String() string {
	var out bytes.Buffer

	out.WriteString("(")
	out.WriteString(ie.Left.String())
	out.WriteString(" " + ie.Operator + " ")
	out.WriteString(ie.Right.String())
	out.WriteString(")")

	return out.String()
}

// Boolean bool类型解析结构定义
type Boolean struct {
	Token token.Token // 词法单元
	Value bool        // 值
}

// expressionNode Boolean实现Expression接口expressionNode方法
func (b *Boolean) expressionNode() {}

// TokenLiteral Boolean实现Node接口TokenLiteral方法
func (b *Boolean) TokenLiteral() string {
	return b.Token.Literal
}

// String Boolean实现Node接口String方法
func (b *Boolean) String() string {
	return b.Token.Literal
}

// IFExpression if表达式解析
//
//	if (条件) {代码块} || if (条件) {代码块} else {代码块}
type IFExpression struct {
	Token       token.Token     // 词法单元
	Condition   Expression      // if表达式中的 Condition 条件部分
	Consequence *BlockStatement // if condition 为true的分支
	Alternative *BlockStatement // if condition 为false的 else 分支
}

// expressionNode IFExpression实现Expression接口expressionNode方法
func (ie *IFExpression) expressionNode() {}

// TokenLiteral IFExpression实现Node接口TokenLiteral方法
func (ie *IFExpression) TokenLiteral() string {
	return ie.Token.Literal
}

// String IFExpression实现Node接口String方法
func (ie *IFExpression) String() string {
	var out bytes.Buffer

	out.WriteString("if")
	out.WriteString(ie.Condition.String())
	out.WriteString(" ")
	out.WriteString(ie.Consequence.String())

	if ie.Alternative != nil {
		out.WriteString("else")
		out.WriteString(ie.Alternative.String())
	}

	return out.String()
}

// FunctionLiteral 函数表达式字面量结构体定义
//
//	fn (参数列表) {代码块}
type FunctionLiteral struct {
	Token      token.Token     // 词法单元
	Parameters []*Identifier   // 参数列表
	Body       *BlockStatement // 函数体
	Name       string          // 函数名
}

// expressionNode FunctionLiteral实现Expression接口expressionNode方法
func (fl *FunctionLiteral) expressionNode() {}

// TokenLiteral FunctionLiteral实现Node接口TokenLiteral方法
func (fl *FunctionLiteral) TokenLiteral() string {
	return fl.Token.Literal
}

// String FunctionLiteral实现Node接口String方法
func (fl *FunctionLiteral) String() string {
	var out bytes.Buffer

	var params []string
	for _, p := range fl.Parameters {
		params = append(params, p.String())
	}

	out.WriteString(fl.TokenLiteral())
	if fl.Name != "" {
		out.WriteString(fmt.Sprintf("<%s>", fl.Name))
	}
	out.WriteString("(")
	out.WriteString(strings.Join(params, ", "))
	out.WriteString(") ")
	out.WriteString(fl.Body.String())

	return out.String()
}

// CallExpression 调用表达式结构体
//
//	标识符/表达式 (参数/表达式列表) : add(2, 3)、call(1, 2 * 3, fn(x, y) { x + y; })
//	在解析的时候，以 ( 作为分割，左边视作将调用的函数，右边除了 ) 外都做为参数。那么可以认为 ( 就是一个中缀运算符，只要为 ( 添加运算符优先级并注册中缀解析函数即可
type CallExpression struct {
	Token     token.Token  // 词法单元
	Function  Expression   // 标识符或者函数字面量
	Arguments []Expression // 参数/表达式列表
}

// expressionNode CallExpression实现Expression接口expressionNode方法
func (ce *CallExpression) expressionNode() {}

// TokenLiteral CallExpression实现Node接口TokenLiteral方法
func (ce *CallExpression) TokenLiteral() string {
	return ce.Token.Literal
}

// String CallExpression实现Node接口String方法
func (ce *CallExpression) String() string {
	var out bytes.Buffer

	var params []string
	for _, p := range ce.Arguments {
		params = append(params, p.String())
	}

	out.WriteString(ce.Function.String())
	out.WriteString("(")
	out.WriteString(strings.Join(params, ", "))
	out.WriteString(")")

	return out.String()
}

// StringLiteral 字符串字面量
type StringLiteral struct {
	Token token.Token // 词法单元
	Value string      // 字符串值
}

// expressionNode StringLiteral实现Expression接口expressionNode方法
func (sl *StringLiteral) expressionNode() {}

// TokenLiteral StringLiteral实现Expression接口TokenLiteral方法
func (sl *StringLiteral) TokenLiteral() string {
	return sl.Token.Literal
}

// String StringLiteral实现Expression接口String方法
func (sl *StringLiteral) String() string {
	return sl.Value
}

// ArrayLiteral 数组字面量
type ArrayLiteral struct {
	Token    token.Token  // 数组的第一个字符的词法单元, 也就是 '[' 符号
	Elements []Expression // 数组元素
}

// expressionNode ArrayLiteral实现Expression接口expressionNode方法
func (al *ArrayLiteral) expressionNode() {}

// TokenLiteral ArrayLiteral实现Expression接口TokenLiteral方法
func (al *ArrayLiteral) TokenLiteral() string {
	return al.Token.Literal
}

// String ArrayLiteral实现Expression接口String方法
func (al *ArrayLiteral) String() string {
	var out bytes.Buffer

	var es []string
	for _, e := range al.Elements {
		es = append(es, e.String())
	}

	out.WriteString("[")
	out.WriteString(strings.Join(es, ", "))
	out.WriteString("]")

	return out.String()
}

// TupleLiteral 元组字面量 - 2023/6/21
type TupleLiteral struct {
	Token    token.Token  // 元组的第一个字符的词法单元, '(' 符号
	Elements []Expression // 元组元素
}

// expressionNode TupleLiteral实现Expression接口expressionNode方法
func (t *TupleLiteral) expressionNode() {}

// TokenLiteral TupleLiteral实现Expression接口TokenLiteral方法
func (t *TupleLiteral) TokenLiteral() string {
	return t.Token.Literal
}

// String TupleLiteral实现Expression接口String方法
func (t *TupleLiteral) String() string {
	var out bytes.Buffer

	var es []string
	for _, e := range t.Elements {
		es = append(es, e.String())
	}

	out.WriteString("(")
	out.WriteString(strings.Join(es, ", "))
	out.WriteString(")")

	return out.String()
}

// IndexExpression 索引运算符表达式结构体定义 arr[idx]
type IndexExpression struct {
	Token token.Token // 词法单元, 目前来说是 '['
	Left  Expression  // 左边的表达式. 正在访问的对象，可以是任何类型，包括标识符、数组字面量、函数调用等
	Index Expression  // 索引表达式，可以是任何类型，但是它必须产生出一个整数
}

// expressionNode IndexExpression实现Expression接口expressionNode方法
func (ie *IndexExpression) expressionNode() {}

// TokenLiteral IndexExpression实现Expression接口TokenLiteral方法
func (ie *IndexExpression) TokenLiteral() string {
	return ie.Token.Literal
}

// String IndexExpression实现Expression接口String方法
func (ie *IndexExpression) String() string {
	var out bytes.Buffer

	out.WriteString("(")
	out.WriteString(ie.Left.String())
	out.WriteString("[")
	out.WriteString(ie.Index.String())
	out.WriteString("]")
	out.WriteString(")")

	return out.String()
}

// IndexAssignExpression 基于索引运算符进行赋值的表达式 - 2023/6/19
type IndexAssignExpression struct {
	Token token.Token // 词法单元，这里应该是 =
	Left  Expression  // = 左边应该是索引运算符表达式 - IndexExpression
	Right Expression  // = 右边应该是任意表达式
}

// expressionNode IndexAssignExpression实现Expression接口expressionNode方法
func (ie *IndexAssignExpression) expressionNode() {}

// TokenLiteral IndexAssignExpression实现Expression接口TokenLiteral方法
func (ie *IndexAssignExpression) TokenLiteral() string {
	return ie.Token.Literal
}

// String IndexAssignExpression实现Expression接口String方法
func (ie *IndexAssignExpression) String() string {
	var out bytes.Buffer

	out.WriteString(ie.Left.String())
	out.WriteString(" = ")
	out.WriteString(ie.Right.String())

	return out.String()
}

// HashLiteral 哈希表字面量
type HashLiteral struct {
	Token token.Token               // 词法单元, 表达式开头的第一个字符 即 '{'
	Pairs map[Expression]Expression // 键值对
}

// expressionNode HashLiteral实现Expression接口expressionNode方法
func (hl *HashLiteral) expressionNode() {}

// TokenLiteral HashLiteral实现Expression接口TokenLiteral方法
func (hl *HashLiteral) TokenLiteral() string {
	return hl.Token.Literal
}

// String HashLiteral实现Expression接口String方法
func (hl *HashLiteral) String() string {
	var out bytes.Buffer

	var pairs []string

	for k, v := range hl.Pairs {
		pairs = append(pairs, k.String()+":"+v.String())
	}

	out.WriteString("{")
	out.WriteString(strings.Join(pairs, ", "))
	out.WriteString("}")

	return out.String()
}
